<template>
  <div class="game-wrapper">
    <h2>单词消消乐</h2>
    <p class="hint">点击匹配的单词和释义来消除它们</p>

    <div class="status">
      <span style="margin-right: 49px"
        >配对次数：
        <span style="color: #ff8500; font-weight: bold">{{ matchCount }}</span>
      </span>
      <span
        >剩余配对：
        <span style="color: #ff8500; font-weight: bold"> {{ remainingPairs }} </span>
      </span>
    </div>
    <div class="grid" v-if="state.checkDatas.length !== words.length">
      <div
        v-for="word in words"
        :key="word.id"
        class="word-block"
        :class="{ selected: selectedIds.includes(word.id), checked: handPipei(word.pairId) }"
        @click="handleSelect(word, handPipei(word.pairId))"
      >
        {{ word.text }}
      </div>

      <dialog />
    </div>

    <div v-else class="againBox">
      <div class="btn" @click="again">再玩一次</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import _ from 'lodash';
import { ref, computed, watch, reactive } from 'vue';

interface WordItem {
  id: number;
  text: string;
  type: 'en' | 'zh';
  pairId: number;
}
const props = defineProps({
  answer: {
    type: String,
    default: () => '[]' as any,
  },
});
const rawPairs = [
  ['music', '音乐'],
  ['important', '重要的'],
  ['interesting', '有趣的'],
  ['family', '家庭'],
  ['friend', '朋友'],
  ['class', '班级；课程'],
  ['computer', '电脑'],
  ['teacher', '老师'],
  ['book', '书'],
  ['home', '家庭'],
];
const state = reactive({
  rawPairs: [] as any,
  checkDatas: [] as any,
});
let idCounter = 0;
const generateWords = (): WordItem[] => {
  const list: WordItem[] = [];
  state.rawPairs.forEach((pair: any, idx: any) => {
    list.push({ id: idCounter++, text: pair[0], type: 'en', pairId: idx });
    list.push({ id: idCounter++, text: pair[1], type: 'zh', pairId: idx });
  });
  return shuffle(list);
};

function shuffle<T>(arr: T[]): T[] {
  return arr.slice().sort(() => Math.random() - 0.5);
}

const words = ref<WordItem[]>([]);
const selectedIds = ref<number[]>([]);
const matchCount = ref(0);

const remainingPairs = computed(() => {
  const selectIds = state.checkDatas.map((v: any) => v.id);
  const deep = words.value.filter((v: any) => !selectIds.includes(v.id));
  return Math.round(deep.length / 2); // 向上取整
});

function handleSelect(word: WordItem, selected: Boolean) {
  if (selected) return;
  if (selectedIds.value.includes(word.id)) return;

  selectedIds.value.push(word.id);
  state.checkDatas.push(word);
  if (selectedIds.value.length === 2) {
    const [first, second] = selectedIds.value.map(id => words.value.find(w => w.id === id)!);

    if (first.pairId === second.pairId && first.type !== second.type) {
      // 匹配成功，移除配对
      //   words.value = words.value.filter(w => w.pairId !== first.pairId);
      matchCount.value++;
    } else {
      state.checkDatas = _.filter(state.checkDatas, v => v.id !== first.id && v.id !== second.id);
    }
    // 延迟清除选择状态
    setTimeout(() => {
      selectedIds.value = [];
    }, 300);
  }
}
// 匹配成功，隐藏变量，继续站位
const handPipei = (pairId: any) => {
  const temp = _.filter(state.checkDatas, v => v.pairId === pairId);
  return temp.length === 2;
};

const again = () => {
  state.checkDatas = [];
  matchCount.value = 0;
  selectedIds.value = [];
};

const decodeHtml = (str: any) => {
  const txt = document.createElement('textarea');
  txt.innerHTML = str;
  return txt.value;
};

watch(
  () => props.answer,
  (newVal: any) => {
    try {
      // 判断字符串是否是数组
      const arrayData = decodeHtml(newVal);
      if (arrayData) {
        console.log('是数组');
        state.rawPairs = JSON.parse((props.answer || '[]').replaceAll("'", '"'));
        words.value = generateWords();
      } else {
        console.log('不是数组');
      }
    } catch (e) {
      console.log('不是数组');
    }
  },
  {
    immediate: true,
  },
);
</script>

<style lang="scss" scoped>
.game-wrapper {
  margin: 0 auto;
  text-align: center;
  font-family: 'Helvetica Neue', sans-serif;
}

.hint {
  color: #888;
  font-size: 14px;
  margin-bottom: 10px;
}

.status {
  display: flex;
  justify-content: center;
  // justify-content: space-between;
  margin: 10px 0;
  font-weight: bold;
}

.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}

.againBox {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 300px;
  height: 100px;

  .btn {
    width: 112px;
    height: 32px;
    background: #ffffff;
    border-radius: 8px;
    border: 1px solid #eeeeee;
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;

    font-family: PingFangSC, PingFang SC;
    font-weight: 400;
    font-size: 14px;
    color: #6a6a6a;
    line-height: 24px;
    text-align: left;
    font-style: normal;
  }
}

.word-block {
  background-color: #f0f4ff;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease;
  user-select: none;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 172px;
  height: 100px;
  background: rgba(67, 60, 254, 0.05);
  border-radius: 4px;
  border: 1px solid rgba(67, 60, 254, 0.2);
}

.word-block.selected {
  background-color: #ff8c1a;
  color: white;
  font-weight: bold;
}

.word-block.checked {
  // background-color: rgba(67, 60, 254, 0.05);
  // color: rgba(67, 60, 254, 0);
  background-color: #f9f9f9;
  color: #f9f9f9;
  border: 1px solid #f9f9f9;
}
</style>
